/* Copyright 2021-2022 NXP
 *
 * NXP Confidential. This software is owned or controlled by NXP and may only
 * be used strictly in accordance with the applicable license terms.  By
 * expressly accepting such terms or by downloading, installing, activating
 * and/or otherwise using the software, you are agreeing that you have read,
 * and that you agree to comply with and are bound by, such license terms.  If
 * you do not agree to be bound by the applicable license terms, then you may
 * not retain, install, activate or otherwise use the software.
 */

#include "board.h"
#include "fsl_adapter_gpio.h"
#include <uwb_bus_interface.h>
#ifdef CPU_MCXW727CMFTA
#include <MCXW727C_cm33_core0.h> 
#elif defined K32W1480
#include <K32W1480.h>  
#endif
#include "phNxpLogApis_Board.h"


GPIO_HANDLE_DEFINE(g_UwbIrqGpioHandle);


void uwb_bus_io_irq_cb(void *args)
{
    uwb_bus_board_ctx_t *pCtx = (uwb_bus_board_ctx_t *)args;
//    PRINTF("IRQ ind\r\n");
    // Signal TML read task
    phOsalUwb_ProduceSemaphore(pCtx->mIrqWaitSem);
}

uwb_bus_status_t uwb_bus_io_deinit(uwb_bus_board_ctx_t *pCtx)
{
//    phOsalUwb_SetMemory(mCallbacks, 0, sizeof(uwbs_io_callback) * FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS);
	HAL_GpioDeinit(g_UwbIrqGpioHandle);
	return kUWB_bus_Status_OK;
}

uwb_bus_status_t uwb_bus_io_init(uwb_bus_board_ctx_t *pCtx)
{
    hal_gpio_pin_config_t  UwbIrqPinCfg = {
    		.direction = kHAL_GpioDirectionIn,
			.level = 1,
			.port = 2,
			.pin = BOARD_INITUWBIRQ_UWB_IRQ_N_PIN,
    };
    HAL_GpioInit(g_UwbIrqGpioHandle, &UwbIrqPinCfg);
    uwb_bus_io_uwbs_irq_enable(pCtx);
    return kUWB_bus_Status_OK;
}

/**
 * @brief
 * Wrapper function for nfc sdk
 * Calls uwb_bus_io_val_set using board ctx
 * @param gpioValue
 */
void nfc_ven_val_set(uint8_t gpioValue)
{
    uwbs_io_state_t gpioSetValue = (uwbs_io_state_t)gpioValue;
    uwb_bus_board_ctx_t board_ctx;
    if (uwb_bus_io_val_set(&board_ctx, kUWBS_IO_O_VENUS_VEN, gpioSetValue) != kUWB_bus_Status_OK) {
        LOG_E("%s : uwb_bus_io_val_set failed", __FUNCTION__);
    }
}

/**
 * @brief
 * Wrapper function for nfc sdk
 * Calls uwb_bus_io_val_get using board ctx
 * @param gpioValue
 * @return uint32_t
 */
uint32_t nfc_ven_val_get(uint8_t gpioValue)
{
    uwbs_io_state_t gpio_val = kUWBS_IO_State_NA;
    uwb_bus_board_ctx_t board_ctx;
    if (uwb_bus_io_val_get(&board_ctx, kUWBS_IO_O_VENUS_VEN, &gpio_val) != kUWB_bus_Status_OK) {
        LOG_E("%s : uwb_bus_io_val_get failed", __FUNCTION__);
    }
    return (uint32_t)gpio_val;
}

/**
 * @brief
 * Wrapper function for nfc sdk
 * Calls uwb_bus_io_val_get using board ctx
 * @return uint32_t
 */
uint32_t nfc_irq_val_get()
{
    uwbs_io_state_t irq_val = kUWBS_IO_State_NA;
    uwb_bus_board_ctx_t board_ctx;
    if (uwb_bus_io_val_get(&board_ctx, kUWBS_IO_I_VENUS_IRQ, &irq_val) != kUWB_bus_Status_OK) {
        LOG_E("%s : uwb_bus_io_val_get failed", __FUNCTION__);
    }
    return (uint32_t)irq_val;
}

uwb_bus_status_t uwb_bus_io_val_set(uwb_bus_board_ctx_t *pCtx, uwbs_io_t gpioPin, uwbs_io_state_t gpioValue)
{
    uwb_bus_status_t return_status;
    GPIO_Type *base;
    uint32_t port;
    uint32_t pin;
    if (pCtx == NULL) {
        LOG_E("uwbs bus context is NULL");
        return kUWB_bus_Status_FAILED;
    }

    switch (gpioPin) {
    case kUWBS_IO_O_HELIOS_SYNC: {
    	GPIO_PinWrite(BOARD_INITUWBPINS_GPIO03_WAKEUP_GPIO, BOARD_INITUWBPINS_GPIO03_WAKEUP_PIN, gpioValue);
        return_status = kUWB_bus_Status_OK;
    } break;
    case kUWBS_IO_O_ENABLE_HELIOS: {
//    	PRINTF("set CE pin: %d,\r\n", gpioValue);
		GPIO_PinWrite(BOARD_INITUWBPINS_UWB_CHIPENABLE_GPIO, BOARD_INITUWBPINS_UWB_CHIPENABLE_PIN, gpioValue);
        return_status = kUWB_bus_Status_OK;
    } break;
    case kUWBS_IO_O_HELIOS_RTC_SYNC:
        /* Not needed for RV4 */
        return_status = kUWB_bus_Status_OK;
        break;
    case kUWBS_IO_O_VENUS_VEN: {

    } break;
    default:
        LOG_E("UWBD IO GPIO Pin not supported");
        return_status = kUWB_bus_Status_FAILED;
        break;
    }
    return return_status;
}

uwb_bus_status_t uwb_bus_io_val_get(uwb_bus_board_ctx_t *pCtx, uwbs_io_t gpioPin, uwbs_io_state_t *pGpioValue)
{
    uwb_bus_status_t return_status = kUWB_bus_Status_OK;
    GPIO_Type *base;
    uint32_t port;
    uint32_t pin;

    if (pCtx == NULL) {
        LOG_E("uwbs bus context is NULL");
        return_status = kUWB_bus_Status_FAILED;
    }
    else {
        switch (gpioPin) {
        case kUWBS_IO_I_UWBS_IRQ: {
            base        = BOARD_INITUWBIRQ_UWB_IRQ_N_GPIO;
            pin         = BOARD_INITUWBIRQ_UWB_IRQ_N_PIN;
            *pGpioValue = (uwbs_io_state_t)GPIO_PinRead(base, pin);
        } break;
        case kUWBS_IO_O_HELIOS_SYNC: {
            base        = BOARD_INITUWBPINS_GPIO03_WAKEUP_GPIO;
            pin         = BOARD_INITUWBPINS_GPIO03_WAKEUP_PIN;
            *pGpioValue = (uwbs_io_state_t)GPIO_PinRead(base, pin);
        } break;
        case kUWBS_IO_O_ENABLE_HELIOS: {
			base        = BOARD_INITUWBPINS_UWB_CHIPENABLE_GPIO;
			pin         = BOARD_INITUWBPINS_UWB_CHIPENABLE_PIN;
			*pGpioValue = (uwbs_io_state_t)GPIO_PinRead(base, pin);
        } break;
        case kUWBS_IO_I_VENUS_IRQ: {
        } break;
        case kUWBS_IO_O_VENUS_VEN: {
        } break;
        default:
            LOG_E("UWBD IO GPIO Pin not supported");
            return_status = kUWB_bus_Status_FAILED;
        }
    }
    return return_status;
}

uwb_bus_status_t uwb_bus_io_irq_dis(uwb_bus_board_ctx_t *pCtx, uwbs_io_t irqPin)
{
    uwb_bus_status_t status = kUWB_bus_Status_FAILED;

    if (pCtx == NULL) {
        LOG_E("uwbs bus context is NULL");
        return status;
    }
    __disable_irq();

    switch (irqPin) {
    case kUWBS_IO_I_UWBS_IRQ: {
//    	HAL_GpioSetTriggerMode(g_UwbIrqGpioHandle, kHAL_GpioInterruptDisable);
    	GPIO_SetPinInterruptConfig(BOARD_INITUWBIRQ_UWB_IRQ_N_GPIO, BOARD_INITUWBIRQ_UWB_IRQ_N_PIN, kGPIO_InterruptStatusFlagDisabled);
    } break;
    case kUWBS_IO_I_VENUS_IRQ: {
    } break;
    default:
        LOG_E("UWBD IO GPIO Pin Interrupt not supported");
        goto end;
    }
    status                    = kUWB_bus_Status_OK;
end:
    __enable_irq();
    __ISB();
    return status;
}

uwb_bus_status_t uwb_bus_io_irq_en(uwb_bus_board_ctx_t *pCtx, uwbs_io_t irqPin, uwbs_io_callback *pCallback)
{
    uwb_bus_status_t status = kUWB_bus_Status_FAILED;

    uint8_t prio;

    if (pCtx == NULL) {
        LOG_E("uwbs bus context is NULL");
        return status;
    }

    /*
     * Note: __disable_irq()/_enable_irq()+__ISB() apparently cause no
     * trouble, but don't match FreeRTOS's portDISABLE_INTERRUPTS/portENABLE_INTERRUPTS
     * definition. Consider using FreeRTOS's macros in case of trouble
     */
    __disable_irq();

    switch (irqPin) {
    case kUWBS_IO_I_UWBS_IRQ: {
    	HAL_GpioSetTriggerMode(g_UwbIrqGpioHandle, kHAL_GpioInterruptRisingEdge);
    	HAL_GpioInstallCallback(g_UwbIrqGpioHandle, pCallback->fn, pCallback->args);
    } break;
    case kUWBS_IO_I_VENUS_IRQ: {

    } break;
    default:
        LOG_E("UWBD IO GPIO Pin Interrupt not supported");
        goto end;
    }
    status = kUWB_bus_Status_OK;
end:
    __enable_irq();
    __ISB();
    return status;
}

uwb_bus_status_t uwb_bus_io_irq_wait(uwb_bus_board_ctx_t *pCtx, uint32_t timeout_ms)
{
    if (pCtx == NULL) {
        LOG_E("uwbs bus context is NULL");
        return kUWB_bus_Status_FAILED;
    }
    if (phOsalUwb_ConsumeSemaphore_WithTimeout(pCtx->mIrqWaitSem, timeout_ms) != UWBSTATUS_SUCCESS) {
        LOG_D("phOsalUwb_ConsumeSemaphore_WithTimeout failed");
        return kUWB_bus_Status_FAILED;
    }
    return kUWB_bus_Status_OK;
}

/* This api is needed only for PNP Firmware and SN110 */
uwb_bus_status_t uwb_bus_io_uwbs_irq_enable(uwb_bus_board_ctx_t *pCtx)
{
    uwbs_io_callback callback;
    if (pCtx == NULL) {
        LOG_E("uwbs bus context is NULL");
        return kUWB_bus_Status_FAILED;
    }
    callback.fn   = uwb_bus_io_irq_cb;
    callback.args = pCtx;
    return uwb_bus_io_irq_en(pCtx, kUWBS_IO_I_UWBS_IRQ, &callback);
}
